using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using ICSharpCode.TextEditor.Document;

namespace ICSharpCode.TextEditor
{
    public class GutterMargin : AbstractMargin, IDisposable
    {
        private int leftPadding = 3;

        private int rightPadding = 7;

      //  private int drawStyle = 0;

        private StringFormat numberStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone();

        public static Cursor RightLeftCursor;

        public override Cursor Cursor => RightLeftCursor;

        public override Size Size => new Size(checked(textArea.TextView.WideSpaceWidth * Math.Max(4, (int)Math.Log10(textArea.Document.TotalNumberOfLines) + 2)), -1);

        public override bool IsVisible => textArea.TextEditorProperties.ShowLineNumbers;

        static GutterMargin()
        {
            Stream manifestResourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream("ICSharpCode.TextEditor.Resources.RightArrow.cur");
            if (manifestResourceStream == null)
            {
                throw new Exception("could not find cursor resource");
            }
            RightLeftCursor = new Cursor(manifestResourceStream);
            manifestResourceStream.Close();
        }

        public void Dispose()
        {
            numberStringFormat.Dispose();
        }

        public GutterMargin(TextArea textArea)
            : base(textArea)
        {
            numberStringFormat.Alignment = StringAlignment.Far;
            numberStringFormat.LineAlignment = StringAlignment.Far;
            numberStringFormat.FormatFlags = StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.NoClip;
        }

        public override void Paint(Graphics g, Rectangle rect)
        {
            if (rect.Width <= 0 || rect.Height <= 0)
            {
                return;
            }
            HighlightColor colorFor = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
            HighlightColor colorFor2 = textArea.Document.HighlightingStrategy.GetColorFor("LineNumbers");
            int fontHeight = textArea.TextView.FontHeight;
            Brush brush = (textArea.Enabled ? BrushRegistry.GetBrush(colorFor2.BackgroundColor) : textArea.TextView.UnenableBackgroundBrush);
            Brush brush2 = BrushRegistry.GetBrush(colorFor2.Color);
            Brush markBrush = new SolidBrush(Color.FromArgb(127, 223, 127));
            if (!textArea.Enabled)
            {
                g.FillRectangle(brush, rect);
            }
            checked
            {
                for (int i = 0; i < unchecked(checked(base.DrawingPosition.Height + textArea.TextView.VisibleLineDrawingRemainder) / fontHeight) + 1; i++)
                {
                    int y = drawingPosition.Y + fontHeight * i - textArea.TextView.VisibleLineDrawingRemainder;
                    Rectangle rectangle = new Rectangle(drawingPosition.X, y, drawingPosition.Width, fontHeight);
                    Rectangle rectangle2 = new Rectangle(rectangle.X + leftPadding, rectangle.Y, rectangle.Width - leftPadding - rightPadding, rectangle.Height);
                    if (!rect.IntersectsWith(rectangle))
                    {
                        continue;
                    }
                    int firstLogicalLine = textArea.Document.GetFirstLogicalLine(textArea.Document.GetVisibleLine(textArea.TextView.FirstVisibleLine) + i);
                    if (firstLogicalLine < textArea.Document.TotalNumberOfLines)
                    {
                        Font font = colorFor2.GetFont(base.TextEditorProperties.FontContainer);
                        if (textArea.Document.TextEditorProperties.ComparisonState)
                        {
                            DrawLineCustomBackground(g, firstLogicalLine, font, markBrush, brush2, rectangle);
                        }
                        else
                        {
                            DrawLineMarkBackground(g, firstLogicalLine, font, markBrush, brush2, rectangle);
                        }
                        g.DrawString((firstLogicalLine + 1).ToString(), font, brush2, rectangle2, numberStringFormat);
                    }
                }
                g.DrawLine(new Pen(colorFor.Color), drawingPosition.X + drawingPosition.Width - 1, rect.Top, drawingPosition.X + drawingPosition.Width - 1, rect.Bottom);
            }
        }

        public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons)
        {
            if (!IsVisible)
            {
                return;
            }
            textArea.SelectionManager.selectFrom.where = 1;
            int logicalLine = textArea.TextView.GetLogicalLine(mousepos.Y);
            if (logicalLine < 0 || logicalLine >= textArea.Document.TotalNumberOfLines)
            {
                return;
            }
            checked
            {
                if ((Control.ModifierKeys & Keys.Shift) != 0)
                {
                    if (!textArea.SelectionManager.HasSomethingSelected && logicalLine != textArea.Caret.Position.Y)
                    {
                        if (logicalLine >= textArea.Caret.Position.Y)
                        {
                            TextLocation position = textArea.Caret.Position;
                            if (logicalLine < textArea.Document.TotalNumberOfLines - 1)
                            {
                                textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, position, new TextLocation(0, logicalLine + 1)));
                                textArea.Caret.Position = new TextLocation(0, logicalLine + 1);
                            }
                            else
                            {
                                textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, position, new TextLocation(textArea.Document.GetLineSegment(logicalLine).Length + 1, logicalLine)));
                                textArea.Caret.Position = new TextLocation(textArea.Document.GetLineSegment(logicalLine).Length + 1, logicalLine);
                            }
                        }
                        else
                        {
                            TextLocation position = textArea.Caret.Position;
                            textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, position, new TextLocation(position.X, position.Y)));
                            textArea.SelectionManager.ExtendSelection(new TextLocation(position.X, position.Y), new TextLocation(0, logicalLine));
                            textArea.Caret.Position = new TextLocation(0, logicalLine);
                        }
                    }
                    else
                    {
                        MouseEventArgs e = new MouseEventArgs(mouseButtons, 1, mousepos.X, mousepos.Y, 0);
                        textArea.RaiseMouseMove(e);
                    }
                }
                else
                {
                    textArea.mousepos = mousepos;
                    TextLocation position = new TextLocation(0, logicalLine);
                    textArea.SelectionManager.ClearSelection();
                    if (logicalLine < textArea.Document.TotalNumberOfLines - 1)
                    {
                        textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, position, new TextLocation(position.X, position.Y + 1)));
                        textArea.Caret.Position = new TextLocation(textArea.Document.GetLineSegment(logicalLine).Length + 1, position.Y);
                    }
                    else
                    {
                        textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, new TextLocation(0, logicalLine), new TextLocation(textArea.Document.GetLineSegment(logicalLine).Length + 1, position.Y)));
                        textArea.Caret.Position = new TextLocation(textArea.Document.GetLineSegment(logicalLine).Length + 1, position.Y);
                    }
                }
            }
        }

        protected virtual void DrawLineMarkBackground(Graphics g, int curLine, Font lineFont, Brush markBrush, Brush drawBrush, Rectangle backgroundRectangle)
        {
            if (!string.IsNullOrEmpty(base.Document.GetLineSegment(curLine).LineMark))
            {
                Rectangle rect = new Rectangle(checked(backgroundRectangle.X + backgroundRectangle.Width - leftPadding - 2), backgroundRectangle.Y, 3, backgroundRectangle.Height);
                g.FillRectangle(markBrush, rect);
            }
        }

        protected virtual void DrawLineCustomBackground(Graphics g, int curLine, Font lineFont, Brush markBrush, Brush drawBrush, Rectangle backgroundRectangle)
        {
            if (!textArea.Document.LineCustomBackgroundColors.ContainsKey(curLine))
            {
                return;
            }
            CustomLineColor customLineColor = textArea.Document.LineCustomBackgroundColors[curLine];
            string text = ((customLineColor == null) ? "" : customLineColor.Tag);
            if (!string.IsNullOrEmpty(text))
            {
                Brush red = Brushes.Red;
                Brush red2 = Brushes.Red;
                Brush red3 = Brushes.Red;
                Rectangle rect = new Rectangle(checked(backgroundRectangle.X + backgroundRectangle.Width - leftPadding - 2), backgroundRectangle.Y, 3, backgroundRectangle.Height);
                switch (text)
                {
                    case "add":
                    case "Inserted":
                        markBrush = red;
                        drawBrush = Brushes.Gray;
                        break;
                    case "modify":
                    case "Modified":
                        markBrush = red2;
                        drawBrush = Brushes.Gray;
                        break;
                    case "delete":
                    case "Deleted":
                        markBrush = red3;
                        drawBrush = Brushes.Gray;
                        break;
                }
                g.FillRectangle(markBrush, rect);
            }
        }
    }
}
